// Copyright 2023 Srhino Co., Ltd. All rights reserved.

package v3

import (
	"context"
	v2 "git.ouryun.cn/lzj1/grpc-bidirectional-stream/pkg/apis/v2"
	ifacev2 "git.ouryun.cn/lzj1/grpc-bidirectional-stream/pkg/interfaces/v2"
	ifacev3 "git.ouryun.cn/lzj1/grpc-bidirectional-stream/pkg/interfaces/v3"
	"git.ouryun.cn/lzj1/grpc-bidirectional-stream/pkg/utils"
	"io"
	"log"
	"net/http"
)

type clientAgent struct {
	cxt        context.Context
	config     *AgentConfig
	restServer utils.RestServer
	grpcServer ifacev2.GrpcServer
}

var _ ifacev3.AgentService = (*clientAgent)(nil)

func NewClientAgent(ctx context.Context, config *AgentConfig) ifacev3.AgentService {
	return &clientAgent{
		cxt:    ctx,
		config: config,
		restServer: utils.NewRestServer(ctx, &utils.RestServerConfig{
			Name:    "RESTful API",
			Address: config.WebAddress,
		}),
		grpcServer: NewGrpcClient(config.GrpcAddress, ctx),
	}
}

func (s *clientAgent) Start() error {
	// 启动gRPC服务
	go func() {
		if err := s.grpcServer.Start(); err != nil {
			log.Println(err)
		}
	}()
	// 启动RESTful API服务
	s.restServer.RegisterHandlerFunc("/", s.restHandler)
	err := s.restServer.Start()
	if err != nil {
		return err
	}
	return nil
}

// 对外提供的接口，接收外部请求转发到gRPC服务
func (s *clientAgent) restHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	respResult := utils.NewEmptyResponseResult()

	streamRequest := &v2.Request{
		Headers: make(map[string]string),
	}
	body, err := io.ReadAll(r.Body)
	if err != nil {
		respResult.Code = 1100
		respResult.Err = "参数错误"
		if _, err := w.Write(respResult.Bytes()); err != nil {
			log.Print(err)
		}
		return
	}
	defer r.Body.Close()

	streamRequest.Body = body
	streamRequest.Method = r.Method
	streamRequest.Url = r.URL.String()
	for k, v := range r.Header {
		streamRequest.Headers[k] = v[0]
	}

	res, err := s.grpcServer.Request(&v2.StreamMessage{
		Message: &v2.StreamMessage_Request{
			Request: streamRequest,
		},
	}, 0)

	if err != nil {
		respResult.Code = 1200
		respResult.Err = err.Error()
		if _, err := w.Write(respResult.Bytes()); err != nil {
			log.Print(err)
		}
		return
	}

	response := res.GetResponse()

	if _, err := w.Write(response.Body); err != nil {
		log.Print(err)
	}

}
